package exp.parser;

import grammar.parser.FuncFParams;
import word.parser.WordElement;

import java.util.ArrayList;
import java.util.List;

public class RelExp extends ExpParser {
    private final ExpParser left;
    private final ExpParser right;
    private final RelOpt opt;

    public RelExp(ExpParser left, ExpParser right, RelOpt opt) {
        super(false, left.isConst() && (right == null || right.isConst()));
        this.left = left;
        this.right = right;
        this.opt = opt;
    }

    public static RelExp parserRelExp() {
        List<ExpParser> expParserList = new ArrayList<>();
        List<RelOpt> optList = new ArrayList<>();
        expParserList.add(AddExp.parserAddExp());
        RelOpt opt = null;
        while (getAnalyzingWord().getType() == WordElement.WordType.LSS ||
                getAnalyzingWord().getType() == WordElement.WordType.LEQ ||
                getAnalyzingWord().getType() == WordElement.WordType.GRE ||
                getAnalyzingWord().getType() == WordElement.WordType.GEQ) {
            switch (getAnalyzingWord().getType()) {
                case LSS:
                    opt = RelOpt.LSS;
                    break;
                case LEQ:
                    opt = RelOpt.LEQ;
                    break;
                case GRE:
                    opt = RelOpt.GRE;
                    break;
                case GEQ:
                    opt = RelOpt.GEQ;
                    break;
                default:
                    throw new RuntimeException("parse rel exp");
            }

            optList.add(opt);
            analyzeNextWord();

            expParserList.add(AddExp.parserAddExp());
        }
        optList.add(null);
        ExpParser left = expParserList.get(0);
        for (int i = 1; i <= expParserList.size(); i++) {
            ExpParser right = i < expParserList.size() ? expParserList.get(i) : null;
            left = new RelExp(left, right, optList.get(i - 1));
        }
        return (RelExp) left;
    }

    @Override
    public LVal toLVal() {
        return null;
    }

    @Override
    public Integer compute() {
        int l = left.getValue();
        if (right == null) {
            return l;
        }
        int r = right.getValue();
        switch (opt) {
            case LSS:
                return l < r ? 1 : 0;
            case LEQ:
                return l <= r ? 1 : 0;
            case GRE:
                return l > r ? 1 : 0;
            case GEQ:
                return l >= r ? 1 : 0;
        }
        return 0;
    }

    @Override
    public FuncFParams.FuncFParam checkDimension() {
        return new FuncFParams.FuncFParam(0, 0);
    }

    public enum RelOpt {
        LSS,
        LEQ,
        GRE,
        GEQ
    }
}
